/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package modules.enderecamento.models.dao;

/**
 *
 * @author Clezio
 */
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import modules.enderecamento.exception.EspacoExcedidoPaleteException;
import modules.enderecamento.exception.EspacoExcedidoRuaException;
import modules.enderecamento.exception.PaleteNaoEnderecadoException;
import modules.enderecamento.exception.PaleteOcupadoException;
import modules.enderecamento.models.dto.Enderecamento;
import modules.enderecamento.models.dto.Palete;
import modules.enderecamento.models.dto.Produto;
import modules.enderecamento.util.HibernateUtil;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

public class PaleteDAO {

    private SessionFactory sessionFactory;

    public PaleteDAO() throws Exception {
        sessionFactory = HibernateUtil.getSessionFactory();
    }

    public void save(Palete palete) throws Exception {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        if (palete.getId() > 0) {
            //Checa espaço no palete
            List<Enderecamento> listEnderecamento = session.createCriteria(Enderecamento.class).add(Restrictions.eq("palete.id", palete.getId())).list();
            double cubagemOcupada = 0;
            for (int i = 0; i < listEnderecamento.size(); i++) {
                Produto produto = listEnderecamento.get(i).getProduto();
                int qtde = listEnderecamento.get(i).getQuantidade();
                BigDecimal produtoAltura = produto.getAltura().divide(BigDecimal.valueOf(100));
                BigDecimal produtoComprimento = produto.getComprimento().divide(BigDecimal.valueOf(100));
                BigDecimal produtoLargura = produto.getLargura().divide(BigDecimal.valueOf(100));
                BigDecimal subTotal = (produtoAltura.multiply(produtoComprimento).multiply(produtoLargura));
                cubagemOcupada += subTotal.doubleValue() * qtde;
            }
            if(cubagemOcupada > palete.getCubagem()){
                tx.rollback();
                session.close();
                throw new EspacoExcedidoPaleteException("Não foi possível alterar Palete.\r\n"
                        + "A cubagem ocupada é maior que a atual.");
            }else{
                session.update(palete);
            }
        } else {
            session.save(palete);
        }
        session.flush();
        tx.commit();
        session.close();
    }

    public java.util.List getList(String condicao) throws Exception {
        Session session = sessionFactory.openSession();
        Query query = session.createQuery(condicao);
        List paletes = query.list();
        session.flush();
        session.close();
        return paletes;
    }

    public Palete retrieve(Integer pk) throws Exception {
        Session session = sessionFactory.openSession();
        Palete palete = (Palete) session.load(Palete.class, pk);
        Palete paleteDTO = null;
        if (palete != null) {
            paleteDTO = mountDto(palete);
        }
        session.flush();
        session.close();
        return paleteDTO;
    }

    public void delete(Palete palete) throws Exception {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        session.delete(palete);
        session.flush();
        tx.commit();
        session.close();
    }

    public Palete mountDto(Palete palete) throws Exception {
        Palete paleteDTO = new Palete();
        paleteDTO.setId(palete.getId());
        paleteDTO.setCubagem(palete.getCubagem());
        paleteDTO.setAtivo(palete.isAtivo());
        paleteDTO.setRua(new RuaDAO().mountDto(palete.getRua()));
        return paleteDTO;
    }

    public void moverPalete(Palete palete) throws EspacoExcedidoRuaException {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        Integer qtdePaletes = session.createCriteria(Palete.class).add(Restrictions.eq("rua.id", palete.getRua().getId())).list().size();
        if (qtdePaletes >= palete.getRua().getQuantidadePaletes()) {
            tx.rollback();
            session.close();
            throw new EspacoExcedidoRuaException("A quantidade de paletes excede a quantidade máxima permitida para esta Rua.");
        } else {
            if (palete.getId() > 0) {
                session.update(palete);
            } else {
                session.save(palete);
            }
        }
        session.flush();
        tx.commit();
        session.close();
    }

    public List<Palete> getListPaleteEnderecadoVazio() {
        Session session = sessionFactory.openSession();
        List<Palete> paletes = session.createCriteria(Palete.class)
                .add(Restrictions.isEmpty("enderecamentos"))
                .add(Restrictions.isNotNull("rua"))
                .addOrder(Order.asc("id"))
                .list();
        session.flush();
        List<Palete> paletesRetorno = new ArrayList<Palete>(paletes);
        session.close();
        return paletesRetorno;
    }

    public void removerPaleteVazio(Palete paleteParametro) throws PaleteOcupadoException, PaleteNaoEnderecadoException {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        Palete palete = (Palete) session.load(Palete.class, paleteParametro.getId());
        if(palete.getEnderecamentos().size() > 0){
            tx.rollback();
            session.close();
            throw new PaleteOcupadoException("O Palete informado não se encontra vazio.");
        }
        if(palete.getRua() == null){
            tx.rollback();
            session.close();
            throw new PaleteNaoEnderecadoException("O Palete informado não se encontra endereçado.");
        }
        palete.setRua(null);
        session.save(palete);
        session.flush();
        tx.commit();
        session.close();
    }
}
